package com.ruyuan2020.furnishing.common.metrics;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Configuration
public class DubboThreadMetricsConfig {

    @Value("${dubbo.protocol.port:20880}")
    private Integer port;

    @Autowired
    private MeterRegistry meterRegistry;

    @PostConstruct
    public void init() {
        new Thread(() -> {
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
                URL url = new URL(null, null, port);
                ThreadPoolExecutor executor = (ThreadPoolExecutor) executorRepository.getExecutor(url);
                if (Objects.nonNull(executor) && !Objects.equals(executor.getMaximumPoolSize(), Integer.MAX_VALUE)) {
                    Gauge.builder("dubbo.thread.pool.core.size", executor, ThreadPoolExecutor::getCorePoolSize)
                            .description("核心线程数")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.largest.size", executor, ThreadPoolExecutor::getLargestPoolSize)
                            .description("历史最高线程数")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.max.size", executor, ThreadPoolExecutor::getMaximumPoolSize)
                            .description("最大线程数")
                            .baseUnit("threads")
                            .strongReference(true)
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.active.size", executor, ThreadPoolExecutor::getActiveCount)
                            .description("活跃线程数")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.thread.count", executor, ThreadPoolExecutor::getPoolSize)
                            .description("当前线程数")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.queue.size", executor, it -> it.getQueue().size())
                            .description("队列大小")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.taskCount", executor, ThreadPoolExecutor::getTaskCount)
                            .description("任务总量")
                            .baseUnit("threads")
                            .register(meterRegistry);
                    Gauge.builder("dubbo.thread.pool.completedTaskCount", executor, ThreadPoolExecutor::getCompletedTaskCount)
                            .description("已完成的任务量")
                            .baseUnit("threads")
                            .register(meterRegistry);
                }
            }
        }).start();
    }
}
